#ifndef XPM_DOC_MODEL_SDF_SIGN_H
#define XPM_DOC_MODEL_SDF_SIGN_H

#include <string>
#include <vector>
#include "SDFIdentifier.h"
#include "SDFDenotation.h"
#include "SDFConnotation.h"
#include "SDFReification.h"

using namespace std;
// type definitions
//#define SDF_NULL '\0'
//#define SDF_STRING '\1'
//#define SDF_NUMBER '\2'
//#define SDF_TRUE '\3'
//#define SDF_FALSE '\4'
//#define SDF_ARRAY '\5'
//#define SDF_NODE '\6'
#define SDF_EMPTY '\7'

namespace xpm {

	class SDFSign {
	public:		
		// iterators
		typedef SDFDenotation::iterator de_iterator;
		typedef SDFReification::iterator rei_iterator;
		typedef SDFConnotation::iterator iterator;
		// construct and deconstruct
		SDFSign(int type);
		// construct with different reification types
		SDFSign(wstring de_str, wstring rei_str);
		SDFSign(wstring de_str, float rei_num);
		SDFSign(wstring de_str, bool rei_bool);
		~SDFSign();
		// common apis
		int type();
		void set_type(int type);
		// common iterator apis		
		
		// denotation apis
		SDFSign::de_iterator de_begin();
		SDFSign::de_iterator de_end();
		wstring de_str() const;
		void set_de_str(wstring de_str);		
		int de_size();
		bool de_empty();
		void de_clear();
		void de_append_literals(wstring literals);
		void de_append_atom_sign(wstring signifier, conex::Term* signified);
		void de_append_map(int pos, wstring signifier, conex::Term* signified);
		// reification apis
		SDFSign::rei_iterator rei_begin();
		SDFSign::rei_iterator rei_end();
		wstring rei_as_string();
		void set_rei_string(wstring str);
		float rei_as_number();
		void set_rei_number(float num);
		bool rei_as_bool();		
		void set_rei_bool(bool bl);		
		int rei_size();
		bool rei_empty();
		void rei_clear();
		void rei_append_literals(wstring literals);
		void rei_append_atom_sign(wstring signifier, conex::Term* signified);
		void rei_append_map(int pos, wstring signifier, conex::Term* signified);
		// connotation apis		
		SDFSign::iterator begin();
		SDFSign::iterator end();
		void push_back(SDFSign* sign);		
		int size();
		bool empty();
		void clear();
		SDFSign* at(int index);
		// to parse apis in syntax s
		int s_start();
		int s_end();
		int s_size();
		void set_s_start(int start);
		void set_s_end(int end);
		// for values
		int v_start();
		int v_end();
		int v_size();
		void set_v_start(int start);
		void set_v_end(int end);
		// for parent link and childen
		SDFSign* parent();
		SDFSign* next();
		SDFSign* next_start();
		void set_parent(SDFSign* parent);		
	private:		
		int _type;
		// for syntax parse
		// for key
		int _s_start;
		int _s_end;
		// for value
		int _v_start;
		int _v_end;
		// parent link
		SDFSign* _parent;
		// next link
		SDFSign* _next_sign;
		SDFSign::iterator _next;
		SDFIdentifier _identifier;
		SDFDenotation _denotation;
		SDFReification _reification;
		SDFConnotation _connotation;
	};
	inline int SDFSign::type() {
		return _type;
	}
	// to parse apis in syntax s
	inline SDFSign* SDFSign::parent() {
		return _parent;
	}
	inline void SDFSign::set_parent(SDFSign* parent) {
		_parent = parent;
	}
	// for key
	inline int SDFSign::s_start() {
		return _s_start;
	}
	inline int SDFSign::s_end() {
		return _s_end;
	}
	inline int SDFSign::s_size() {
		return _s_end - _s_start;
	}
	inline void SDFSign::set_s_start(int start) {
		_s_start = start;
	}
	inline void SDFSign::set_s_end(int end) {
		_s_end = end;
	}
	// for value
	inline int SDFSign::v_start() {
		return _v_start;
	}
	inline int SDFSign::v_end() {
		return _v_end;
	}
	inline int SDFSign::v_size() {
		return _v_end - _v_start;
	}
	inline void SDFSign::set_v_start(int start) {
		_v_start = start;
	}
	inline void SDFSign::set_v_end(int end) {
		_v_end = end;
	}

	// common iterator apis
	inline SDFSign::de_iterator SDFSign::de_begin() { 
		return _denotation.begin(); 
	}
	inline SDFSign::de_iterator SDFSign::de_end() {
		return _denotation.end();
	}
	inline SDFSign::rei_iterator SDFSign::rei_begin() {
		return _reification.begin();
	}
	inline SDFSign::rei_iterator SDFSign::rei_end() {
		return _reification.end();
	}
	inline SDFSign::iterator SDFSign::begin() {
		return _connotation.begin();
	}
	inline SDFSign::iterator SDFSign::end() {
		return _connotation.end();
	}
	// denotation apis
	inline wstring SDFSign::de_str() const{
		return _denotation.de_str();
	}
	inline void SDFSign::set_de_str(wstring de_str) {
		_denotation.set_de_str(de_str);
	}
	inline int SDFSign::de_size() {
		return _denotation.size();
	}
	inline bool SDFSign::de_empty() {
		return _denotation.empty();
	}
	inline void SDFSign::de_clear() {
		_denotation.clear();
	}
	inline void SDFSign::de_append_literals(wstring literals) {
		_denotation.append_literals(literals);
	}
	inline void SDFSign::de_append_atom_sign(wstring signifier, conex::Term* signified) {		
		_denotation.append_atom_sign(signifier, signified);
	}
	inline void SDFSign::de_append_map(int pos, wstring signifier, conex::Term* signified) {
		// covert to denotation position
		pos -= _s_start;
		if ( _denotation.de_str().substr(pos, signifier.length()) == signifier)
		    _denotation.append_map(pos, signifier, signified);
	}
	// reification apis
	inline wstring SDFSign::rei_as_string() {
		return _reification.as_string();
	}
	inline void SDFSign::set_rei_string(wstring str) {
		_reification.set_string(str);
	}
	inline float SDFSign::rei_as_number() {
		return _reification.as_number();
	}
	inline void SDFSign::set_rei_number(float num) {
		_reification.set_number(num);
	}
	inline bool SDFSign::rei_as_bool() {
		return _reification.as_bool();
	}
	inline void SDFSign::set_rei_bool(bool bl) {
		_reification.set_bool(bl);
	}
	inline int SDFSign::rei_size() {
		return _reification.size();
	}
	inline bool SDFSign::rei_empty() {
		return _reification.empty();
	}
	inline void SDFSign::rei_clear() {
		_reification.clear();
	}
	inline void SDFSign::rei_append_literals(wstring literals) {
		_reification.append_literals(literals);
	}
	inline void SDFSign::rei_append_atom_sign(wstring signifier, conex::Term* signified) {
		_reification.append_atom_sign(signifier, signified);
	}
	inline void SDFSign::rei_append_map(int pos, wstring signifier, conex::Term* signified) {
		// covert to reification position
		pos -= _v_start;
		if (_type == SDF_STRING && _reification.as_string().substr(pos, signifier.length()) == signifier)
		    _reification.append_map(pos, signifier, signified);
	}
		// connotation apis		
	inline void SDFSign::push_back(SDFSign* sign) {
		sign->set_parent(this);
		_connotation.push_back(sign);
	}
	inline int SDFSign::size() {
		return _connotation.size();
	}
	inline bool SDFSign::empty() {
		return _connotation.empty();
	}
	inline void SDFSign::clear() {
		_connotation.clear();
	}
	inline SDFSign* SDFSign::at(int index) {
		return _connotation.at(index);
	}
}
#endif